
# =================================================================
# add_source_to_object: 创建普通资源文件的对象文件
#
# 参数:
#   OBJECT_NAME -要创建对象库的名称，_OBJECT后缀会自动添加
#   INCLUDES     -头文件目录集合
#   SOURCES      -资源文件集合
# 示例：
#   add_source_to_object(OBJECT_NAME my_object INCLUDES ${INCLUDE_DIRS} SOURCES ${SOURCE_FILES})
function(add_source_to_object)
    # 定义关键字参数
    set(options)
    set(oneValueArgs NAME)
    set(multiValueArgs INCLUDES SOURCES)

    # 解析参数
    cmake_parse_arguments(ARG
            "${options}"
            "${oneValueArgs}"
            "${multiValueArgs}"
            ${ARGN}
    )

    # 必需参数检查
    if(NOT ARG_NAME)
        message(FATAL_ERROR "Missing required argument: NAME")
    endif()

    if(NOT ARG_SOURCES)
        message(FATAL_ERROR "Missing required argument: SOURCES")
    endif()

    # 创建对象库
    add_library(${ARG_NAME}_OBJECT OBJECT ${ARG_SOURCES})

    # 可选头文件目录
    if(ARG_INCLUDES)
        target_include_directories(${ARG_NAME}_OBJECT PUBLIC ${ARG_INCLUDES})
    endif()

    # 创建接口库
    add_library(${ARG_NAME}_INTERFACE INTERFACE)
    target_link_libraries(${ARG_NAME}_INTERFACE INTERFACE ${ARG_NAME}_OBJECT)
endfunction()

# 为可执行目标添加对象库文件，同时自动包含接口库


# =================================================================
# 全局模块注册函数
#   USAGE:
#     register_global_module(
#         NAME <module_name>
#         FILES <source_files>
#         [AGGREGATE_TO <target_name>]  # 可选：聚合到指定目标
#         [DEPENDS <dependencies>]      # 可选：依赖项
#         [EXTRA_LINK <link_targets>]   # 可选：额外链接目标
#     )
function(register_global_module)
    set(oneValueArgs NAME AGGREGATE_TO)
    set(multiValueArgs FILES DEPENDS DEPENDS_OBJECT DEPENDS_LIB EXTRA_LINK)
    cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

    # 自动前缀逻辑
    if(ARG_AGGREGATE_TO)
        set(FULL_MODULE_NAME "${ARG_AGGREGATE_TO}_${ARG_NAME}")
    else()
        set(FULL_MODULE_NAME "${ARG_NAME}")
    endif()

    # 1. 创建模块对象库（带自动前缀）
    add_library(${FULL_MODULE_NAME}_MODULE_OBJECT OBJECT EXCLUDE_FROM_ALL)

    # 2. 添加模块文件
    if(ARG_FILES)
        target_sources(${FULL_MODULE_NAME}_MODULE_OBJECT PUBLIC
                FILE_SET CXX_MODULES
                TYPE CXX_MODULES
                FILES ${ARG_FILES}
        )
    endif()

    # 3. 处理不同类型的依赖
    # 3.1 普通接口依赖（传递编译选项、头文件路径等）
    if(ARG_DEPENDS)
        target_link_libraries(${FULL_MODULE_NAME}_MODULE_OBJECT
                PUBLIC ${ARG_DEPENDS}
        )
    endif()

    # 3.2 对象库依赖（既传递接口属性，也合并对象文件）
    if(ARG_DEPENDS_OBJECT)
        foreach(dep_obj IN LISTS ARG_DEPENDS_OBJECT)
            # 获取接口库名称（假设命名规范）
            string(REGEX REPLACE "_OBJECT$" "" dep_interface "${dep_obj}")
            set(dep_interface "${dep_interface}_INTERFACE")

            # 传递接口属性
            if(TARGET ${dep_interface})
                target_link_libraries(${FULL_MODULE_NAME}_MODULE_OBJECT
                        PUBLIC ${dep_interface}
                )
            else ()
                message(WARNING "Dependency ${dep_interface} not found for ${FULL_MODULE_NAME}")
            endif()

            # 合并对象文件
            if(TARGET ${dep_obj})
                target_sources(${FULL_MODULE_NAME}_MODULE_OBJECT PUBLIC
                        $<TARGET_OBJECTS:${dep_obj}>
                )
            else ()
                message(WARNING "Dependency ${dep_obj} not found for ${FULL_MODULE_NAME}")
            endif()
        endforeach()
    endif()

    # 3.3 静态库/共享库依赖
    if(ARG_DEPENDS_LIB)
        foreach(lib IN LISTS ARG_DEPENDS_LIB)
            # 静态库可以链接到对象库（传递接口属性）
            if(TARGET ${lib})
                target_link_libraries(${FULL_MODULE_NAME}_MODULE_OBJECT
                        PUBLIC ${lib}
                )
            endif()
        endforeach()
    endif()

    # 4. 创建接口库（带自动前缀）
    add_library(${FULL_MODULE_NAME}_MODULE_INTERFACE INTERFACE)
    target_link_libraries(${FULL_MODULE_NAME}_MODULE_INTERFACE
            INTERFACE ${FULL_MODULE_NAME}_MODULE_OBJECT
    )

    # 5. 额外链接目标
    if(ARG_EXTRA_LINK)
        target_link_libraries(${FULL_MODULE_NAME}_MODULE_OBJECT
                PUBLIC ${ARG_EXTRA_LINK}
        )
    endif()

    # 6. 可选的聚合逻辑
    if(ARG_AGGREGATE_TO)
        # 创建或使用现有的聚合对象库
        if(NOT TARGET ${ARG_AGGREGATE_TO}_OBJECT)
            add_library(${ARG_AGGREGATE_TO}_OBJECT OBJECT EXCLUDE_FROM_ALL)
            add_library(${ARG_AGGREGATE_TO}_INTERFACE INTERFACE)
        endif()

        # 将当前模块添加到聚合库
        target_sources(${ARG_AGGREGATE_TO}_OBJECT PUBLIC
                $<TARGET_OBJECTS:${FULL_MODULE_NAME}_MODULE_OBJECT>
        )
        target_link_libraries(${ARG_AGGREGATE_TO}_INTERFACE
                INTERFACE ${FULL_MODULE_NAME}_MODULE_INTERFACE
        )

        # 为聚合模块添加别名（可选）
        add_library(${ARG_AGGREGATE_TO}::${ARG_NAME} ALIAS ${FULL_MODULE_NAME}_MODULE_INTERFACE)
    endif()

    # 7. 添加模块别名（方便直接引用）
    add_library(${FULL_MODULE_NAME} ALIAS ${FULL_MODULE_NAME}_MODULE_INTERFACE)

    # 8. 为对象库添加别名（可选但推荐）
    add_library(${FULL_MODULE_NAME}_OBJECT ALIAS ${FULL_MODULE_NAME}_MODULE_OBJECT)
endfunction()


# 添加项目子目录
function(add_projects_subdirectory PROJECTS_DIR)
    message(STATUS "start load projects ...")
    file(GLOB project_dirs "${PROJECTS_DIR}/*")
    foreach(subdir IN LISTS project_dirs)
        if(IS_DIRECTORY "${subdir}" AND EXISTS "${subdir}/CMakeLists.txt")
            add_subdirectory("${subdir}")
            # 获取最后一级目录名
            get_filename_component(LAST_DIR "${subdir}" NAME)
        endif()
    endforeach()

    # 这些是备用方案的思路，防止一次性添加太多目标导致cmake运行缓慢。不过这个并没有正式开搞
    ## --------------------------------------选择你的项目--------------------------------
    ## 如果你是在CLion里，那么可以直接在斜杆后面输入首字母，会自动弹出相关项目选项
    #set(TARGET_PROJECT_DIR Projects/driversDevelop)
    ## 对配置项变量进行预处理，包括获取项目名称
    #include(cmake/target_project.cmake)
    #add_executable(${PROJECT_NAME}.elf ${SOURCES})
endfunction()